package com.fattyCorps.battle.service.battle.record;

import com.fattyCorps.battle.service.battle.Battle;
import com.fattyCorps.battle.service.battle.behavior.Behavior;
import com.fattyCorps.battle.service.battle.data.BattleHero;
import com.fattyCorps.battle.service.battle.effect.Effect;
import com.fattyCorps.common.enums.battle.prop.EDynamicProp;
import com.fattyCorps.common.enums.battle.record.ERecEffectPlayOpportunity;
import com.fattyCorps.common.enums.battle.record.ERecEffectType;
import com.fattyCorps.common.enums.battle.triggerCondition.EBehaviorCondition;
import com.fattyCorps.common.obj.msg.server.battle.RecElem;
import com.fattyCorps.common.obj.msg.server.battle.RecElemEffect;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

// 战斗录像
public class BattleRecorder {
    public static enum EDamageType {
        // 白色数字，字号小一些，普通伤害，无需加减号
        NorDamage,
        // 红色数字，字号通用，暴击伤害，无需加减号
        Critical,
        // 绿色数字，字号通用，治疗或复活换血等增加血量，无需加减号
        Treat,
        // 紫色数字，字号通用，debuff伤血，无需加减号
        Dot,
        // 青色数字，字号通用，能量变化，带加减号
        Energy
    }

    List<RecElem> elems = new ArrayList<>();
    Battle battle;
    public BattleRecorder(Battle battle) {
        this.battle = battle;
    }

    private void add(RecElem elem) {
        elems.add(elem);
    }

    public RecElem newEvent(EBehaviorCondition cnd, BattleHero hero) {
        RecElem e = new RecElem();
        e.setCnd(cnd);

        if (hero != null) {
            e.setCaster(hero.getPos());
        }

        this.add(e);

        return e;
    }

    public RecElem lastElem() {
        if (elems.size() == 0) {
            return null;
        }

        return elems.get(elems.size() - 1);
    }

    // 记录行为表现，用第一个有表现的行为做为展示效果
    public void recordBhv(Set<Behavior> bhvs) {
        for (Behavior behavior : bhvs) {
            int displayId = behavior.getMould().getDisplayId();
            if (displayId > 0) {
                battle.getRecorder().lastElem().setDisplayId(displayId);
                break;
            }
        }
    }

    public void recordDamage(EDamageType type, long damage, BattleHero target) {
        RecElem recElem = lastElem();
        RecElemEffect newRecEffect = new RecElemEffect();
        newRecEffect.setOpportunity(ERecEffectPlayOpportunity.AfterTargetUnderAttack);
        newRecEffect.setType(ERecEffectType.Damage);
        newRecEffect.setValue(damage);
        newRecEffect.setExtra(type.ordinal() + "");
        newRecEffect.setTargetPos(target.getPos());
        recElem.getEffects().add(newRecEffect);
    }

    // 记录效果
    public void recordEffect(Effect e) {
        RecElem recElem = lastElem();
        RecElemEffect newRecEffect = new RecElemEffect();
        newRecEffect.setOpportunity(ERecEffectPlayOpportunity.AfterTargetUnderAttack);
        newRecEffect.setExtra(e.isShow() + "");

        switch (e.getMould().getType()) {
            case AddBuff:
                newRecEffect.setType(ERecEffectType.AddBuff);
                newRecEffect.setValue(e.getMould().getBuffId());
                break;
            case RemoveBuff:
                newRecEffect.setType(ERecEffectType.RemoveBuff);
                newRecEffect.setValue(e.getMould().getBuffId());
                break;
            case DynamicProp:
                if (e.getMould().getDynamicCalcTargetProp().equals(EDynamicProp.Energy)) {
                    newRecEffect.setType(ERecEffectType.AddEnergy);
                    newRecEffect.setValue(Integer.valueOf(e.getMould().getDynamicCalcValue()));
                } else {
                    return;
                }
                break;
            default:
                return;
        }

        newRecEffect.setTargetPos(e.getTarget().getPos());
        recElem.getEffects().add(newRecEffect);
    }

    public List<RecElem> getRecords() {
        optimize();
        return this.elems;
    }

    // 清理无效事件
    private void optimize() {
        for (int i = elems.size() - 1; i >= 0; i--) {
            if (elems.get(i).getEffects() == null || elems.get(i).getEffects().size() == 0) {
                EBehaviorCondition cnd = elems.get(i).getCnd();
                if (cnd.equals(EBehaviorCondition.AfterRoundEnd) ||
                        cnd.equals(EBehaviorCondition.AfterSelfActive)) {
                    continue;
                }

                elems.remove(i);
            }
        }
    }
}
